<template>
  <div id="sql-files">
    <div class="scroll-content">
      <el-tree
        ref="sqlTreeRef"
        :data="sqlFileNodes"
        show-checkbox
        node-key="id"
        :default-expanded-keys="defaultExpandedKeys"
        :default-checked-keys="defaultCheckedKeys"
        :expand-on-click-node="false"
      >
        <span slot-scope="{ node, data }" class="custom-tree-node">
          <span>{{ node.label }}</span>
          <span v-if="data.isRoot">
            <el-button
              type="text"
              size="mini"
              :disabled="buildStep[componentInfo.id] === 1"
              @click="() => displayNodes(true)"
            >
              显示所有
            </el-button>
            <el-button
              type="text"
              size="mini"
              :disabled="buildStep[componentInfo.id] === 1"
              @click="() => displayNodes(false)"
            >
              显示未升级
            </el-button>
          </span>
          <span v-else>
            <el-tag v-if="node.disabled" type="info" size="mini">
              {{ buildStep[componentInfo.id] === 1? '组件升级中...' : '当前文件已升级' }}
            </el-tag>
          </span>
        </span>
      </el-tree>
    </div>
    <div class="operation-btns">
      <div style="display: flex;justify-content: center;align-items: center; margin-top: 10px;">
        <el-button size="mini" type="primary" :disabled="buildStep[componentInfo.id] === 1" @click="doBuildOp">构建</el-button>
        <el-button size="mini" @click="cancelSet">取消</el-button>
      </div>
    </div>
  </div>
</template>

<script>
import { mapGetters } from 'vuex'
import { fetchCompUpgradeSqlFiles } from '@/api/project'

export default {
  name: 'SQLFiles',
  props: {
    componentInfo: {
      type: Object,
      required: true
    }
  },
  emits: ['detail-config-build', 'detail-config-cancel'],
  data() {
    return {
      sqlFileNodes: [],
      originalData: [],
      isDisplayAll: false,
      defaultExpandedKeys: [],
      defaultCheckedKeys: []
    }
  },
  computed: {
    ...mapGetters([
      'buildStep',
      'detailConfigs'
    ])
  },
  watch: {
    buildStep: {
      immediate: true,
      handler(newVal) {
        this.dataFlush(newVal[this.componentInfo.id])
      }
    }
  },
  mounted() {
    this.initTreeData()
  },
  methods: {
    initTreeData() {
      const loading = this.$loading({
        lock: true,
        text: '数据初始化中...',
        spinner: 'el-icon-loading',
        background: 'rgba(0, 0, 0, 0.7)'
      })
      fetchCompUpgradeSqlFiles({
        projectId: this.$route.meta.projectId,
        componentId: this.componentInfo.componentId,
        branchTag: this.componentInfo.tag
      }).then(res => {
        const sqlFile = res.data
        if (!sqlFile) {
          this.sqlFileNodes = [{
            id: Date.now(),
            label: '根节点'
          }]
        } else {
          this.originalData = JSON.parse(JSON.stringify(sqlFile))
          this.addSqlFileNode(sqlFile)
        }

        const cfg = this.detailConfigs[this.componentInfo.id]
        if (cfg) {
          const sqlFiles = cfg['sqlFiles']
          if (sqlFiles && sqlFiles.length > 0) {
            this.$refs.sqlTreeRef.setCheckedKeys(sqlFiles)
          }
        }
        loading.close()
      }).catch(err => {
        console.error(err)
        loading.close()
      })
    },

    // 实时刷新树节点数据
    dataFlush(stateStep) {
      if (!this.sqlFileNodes || this.sqlFileNodes.length === 0) {
        return
      }
      this.recursiveFlush(this.sqlFileNodes, stateStep)
    },

    recursiveFlush(sqlNodes, stateStep) {
      sqlNodes.forEach(node => {
        node['disabled'] = stateStep === 1
        const children = node['children']
        if (children && children.length > 0) {
          this.recursiveFlush(children, stateStep)
        }
      })
    },

    addSqlFileNode(sqlFile) {
      this.originalData = JSON.parse(JSON.stringify(sqlFile))
      const rootChildren = []
      this.sqlFileNodes = [{
        id: sqlFile.fileId,
        label: sqlFile.name,
        isRoot: true,
        disabled: this.buildStep[this.componentInfo.id] === 1,
        children: rootChildren
      }]
      this.defaultExpandedKeys.push(sqlFile.fileId)
      this.recursivePushNode(sqlFile.subFiles, rootChildren)
    },

    // 递归添加文件列表节点
    recursivePushNode(sqlFiles, childrenArr) {
      // 子文件为空，则返回不处理
      if (!sqlFiles) {
        return
      }
      // 遍历子文件，若子节点没有下一级节点，说明是文件，查找父级树节点，往children节点中添加子节点；
      // 若存在子节点，说明是目录，则在添加节点信息后还需要添加一个children空节点，递归处理
      sqlFiles.forEach(sqlFile => {
        const subSqlFiles = sqlFile.subFiles
        if (!subSqlFiles) {
          if (this.isDisplayAll) {
            this.pushNode(childrenArr, sqlFile)
            if (!sqlFile.upgradeAlready) {
              this.defaultCheckedKeys.push(sqlFile.fileId)
            }
          } else {
            if (!sqlFile.upgradeAlready) {
              this.pushNode(childrenArr, sqlFile)
              this.defaultCheckedKeys.push(sqlFile.fileId)
            }
          }
        } else {
          const subChildren = []
          childrenArr.push({
            id: sqlFile.fileId,
            label: sqlFile.name,
            isSubRoot: true,
            disabled: this.buildStep[this.componentInfo.id] === 1,
            children: subChildren
          })
          this.recursivePushNode(subSqlFiles, subChildren)
        }
      })
    },
    pushNode(childrenArr, sqlFile) {
      childrenArr.push({
        id: sqlFile.fileId,
        label: sqlFile.name,
        isLeaf: true,
        disabled: this.buildStep[this.componentInfo.id] === 1 ? true : sqlFile.upgradeAlready
      })
    },

    // 显示所有
    displayNodes(val) {
      this.isDisplayAll = val
      this.addSqlFileNode(this.originalData)
    },

    doBuildOp() {
      this.saveCfg()
      this.$emit('detail-config-build')
    },

    // 保存配置信息，在切换tab页时由父组件调用
    saveCfg() {
      const selectNodes = this.$refs.sqlTreeRef.getCheckedNodes()
      const selectSqlFiles = []
      selectNodes.forEach(node => {
        if (node.isLeaf) {
          selectSqlFiles.push(node.id)
        }
      })
      this.$store.commit('project/SET_DETAIL_CONFIG', {
        componentId: this.componentInfo.id,
        sqlFiles: selectSqlFiles
      })
    },

    cancelSet() {
      this.$emit('detail-config-cancel')
    }
  }
}
</script>

<style scoped>
#sql-files {
  width: 100%;
  height: 500px;
  text-align: center;
  position: relative;
  padding: 4px;
  box-sizing: border-box;
}

.operation-btns {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  padding: 4px;
  z-index: 2000;
}

.scroll-content {
  height: 450px;
  overflow: auto;
}

.custom-tree-node {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 14px;
  padding-right: 8px;
}
</style>
